#ifndef FIFO_H
#define FIFO_H
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "testbase.h"

/*
    mkfifo fifo_test  先入先出
    unlink fifo_test
*/

class Fifo : public TestBase {
    enum : int {
        READ = 0x01,
        WRITE = 0x02,
        DEL = 0x04
    };

    int parse() {
        int cmd = 0;
        if(argc_ > 1) {
            const std::string str = argv_[1];
            for(const auto& ch : str) {
                if(ch == 'R' || ch == 'r') cmd |= READ;
                else if(ch == 'W' || ch == 'w') cmd |= WRITE;
                else if(ch == 'D' || ch == 'd') cmd |= DEL;
            }
        }
        return cmd;
    }

public:
    Fifo(int argc=0, char** argv=nullptr)
        : TestBase(argc, argv)
        , cmd(parse())
        , valid(!mkfifo(path, 0777))
        , fd(-1)
    {

    }

    void read() {
        char buf[1024]{};
        int len = ::read(fd, buf, sizeof(buf));
        if(len>0) cout << "read : " << buf << endl;
        else puts("read failed");
    }

    void write(const std::string& str) {
        std::size_t len = ::write(fd, str.data(), str.size());
        if(len != str.size()) puts("write failed");
    }

    void test() override {
        if(!valid) {
            puts("test fail");
            return;
        }

        fd = open(path, O_RDWR);
        if(fd < 0) {
            puts("open fail");
            return;
        }

        if(cmd & WRITE) {
            cout << "input send data : ";
            std::string str;
            cin >> str;
            write(str);
        }

        if(cmd & READ) {
            read();
        }

        close(fd);

        if(cmd & DEL) {
            if(!unlink(path)) puts("del fail");
        }
    }

private:
    const char* path = "fifo_test";
    const int cmd;
    bool valid;
    int fd;
};

#endif // FIFO_H
